package org.nbict.iot.task.once.schedule;

import com.alibaba.fastjson.JSON;
import org.nbict.iot.Pair;
import org.nbict.iot.persist.pool.DbRepository;
import org.nbict.iot.persist.repo.MongoRepo;
import org.nbict.iot.persist.repo.MysqlRepo;
import org.nbict.iot.persist.repo.RedisRepo;
import org.nbict.iot.task.once.Pointer;
import org.nbict.iot.task.once.TimeSpan;
import org.nbict.iot.task.once.TimeSpanWindow;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 存在锁竞争问题
 * Created by songseven on 18/7/17.
 */
public class DumpRunning  implements Runnable  {

    private RedisRepo redisRepo;

    private MongoRepo mongoRepo;

    private MysqlRepo mysqlRepo;

    private Long delay;

    public DumpRunning() {
        redisRepo = (RedisRepo) DbRepository.REDIS.getInstance();
        mongoRepo = (MongoRepo) DbRepository.MONGO.getInstance();
        mysqlRepo = (MysqlRepo) DbRepository.MYSQL.getInstance();
        this.delay = 3 * 24 * 3600l; //3天
    }

    @Override
    public void run() {
        System.out.println(new Date() + " => begin dump...");
        Set<String> cars = redisRepo.getKeys("[a-zA-Z_/d]*"); //LJU*
        cars.forEach(car-> {
            System.out.println(car);
            TimeSpanWindow journey = new TimeSpanWindow(car);

            Set<String> pointers = redisRepo.getZSet(car, 0l, -1l);
            if (pointers != null) {
                pointers.forEach(tuple -> {
                    Pointer p = JSON.parseObject(tuple, Pointer.class);
                    journey.take(p);
                });
            }

            //计算行程
            List<TimeSpan> runnings = new ArrayList<>();
            Long preSpanEndTimestamp = 0l;
            for (Pair<Pointer, Pointer> span : journey.getHolder()) {
                Long current = System.currentTimeMillis() / 1000;
                if (current - span.getRight()
                        .currentTime() > delay) { //导出三天之前行程
                    redisRepo.removeWithin(car, preSpanEndTimestamp, span.getLeft().currentTime()); //删除前一段
                    redisRepo.removeWith(car, span.getLeft().currentTime(), span.getRight().currentTime()); //删除本段
                    preSpanEndTimestamp = span.getRight().currentTime();

                    TimeSpan time = new TimeSpan(car,
                            span.getLeft().currentTime(), //起始时间
                            span.getRight().currentTime(),//结束时间
                            span.getLeft().getLon(),//起始经度
                            span.getLeft().getLat(),//起始纬度
                            span.getRight().getLon(),//结束经度
                            span.getRight().getLat(),//结束纬度
                            span.getRight().getSoc() - span.getLeft().getSoc(),
                            "R");//能耗

                    runnings.add(time);
                }
            }
            //插入行驶记录
            if (!runnings.isEmpty()) {
                mysqlRepo.insertJourney(runnings);
            }

            //计算充电
            List<TimeSpan> charges = new ArrayList<>();
            journey.chargeHolder().forEach(span -> {
                //debug
                Long current = System.currentTimeMillis() / 1000;
                if (current - span.getRight()
                        .currentTime() > delay) {
                    TimeSpan time = new TimeSpan(car,
                            span.getLeft().currentTime(), //起始时间 有可能为null
                            span.getRight().currentTime(),//结束时间
                            span.getLeft().getLon(),//起始经度
                            span.getLeft().getLat(),//起始纬度
                            span.getRight().getLon(),//结束经度
                            span.getRight().getLat(),//结束纬度
                            span.getRight().getSoc() - span.getLeft().getSoc(), //soc变化
                            "C"); //充电状态
                    charges.add(time);
                }
            });
            //插入充电记录
            if (!charges.isEmpty()) {
                mysqlRepo.insertJourney(charges);
            }
        });
        System.out.println("end dump...");
    }
    
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newScheduledThreadPool(1);
        for (int i = 0; i < 1; i++) {
            executorService.submit(new DumpRunning());
        }

        Runtime.getRuntime().addShutdownHook(new Thread() {
            @Override
            public void run() {
                //TODO
                executorService.shutdown();
            }
        });
    }
}
